package cn.workreport.modules.report.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.Week;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.workreport.modules.report.dto.FillData;
import cn.workreport.modules.report.dto.WeekExportDTO;
import cn.workreport.modules.common.vo.PageVO;
import cn.workreport.modules.report.mapper.ReportMapper;
import cn.workreport.modules.report.entity.ReportEntity;
import cn.workreport.modules.common.po.PagePO;
import cn.workreport.modules.report.po.ReportPO;
import cn.workreport.modules.report.service.IReportService;
import cn.workreport.modules.users.entity.UserEntity;
import cn.workreport.util.*;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import java.io.*;
import java.util.*;

@Slf4j
@Service("reportService")
public class ReportServiceImpl extends ServiceImpl<ReportMapper, ReportEntity> implements IReportService {
    /**
     * 体检关联性配置默认数据导入模板
     */
    private final String workRportTemplate = "templates" + File.separator + "workRportTemplate.xlsx";


    @Override
    public PageVO<ReportEntity> queryPage(PagePO<ReportPO> params) {
        IPage<ReportEntity> page = new PageQueryUtil<ReportEntity>().getPage(params);

        // 取出当前登录用户信息
        UserEntity currentLoginUser = UserChacheFromToken.getUser();

        LambdaQueryWrapper<ReportEntity> wrapper = new LambdaQueryWrapper<ReportEntity>()
                .eq(ReportEntity::getCreatorId, currentLoginUser.getId())
                .ge(ObjectUtil.isNotNull(params.getStartDateTime()), ReportEntity::getReportTime, params.getStartDateTime())
                .le(ObjectUtil.isNotNull(params.getEndDateTime()), ReportEntity::getReportTime, params.getEndDateTime())
                .orderByAsc(ReportEntity::getReportTime, ReportEntity::getCreatedTime);
        // 方法外移会看齐来比较简洁
        IPage<ReportEntity> result = this.page(page,wrapper);
        return new PageVO<ReportEntity>(result);
    }

    /**
     *  查询当前登录用户的日报列表
     * @param params
     * @return
     */
    public List<ReportEntity> queryUserReportList(ReportPO params) {
        // 取出当前登录用户信息
        LambdaQueryWrapper<ReportEntity> wrapper = new LambdaQueryWrapper();
        wrapper.eq(ReportEntity::getCreatorId, UserChacheFromToken.getUserId());
        wrapper.ge(ObjectUtil.isNotNull(params.getStartDateTime()), ReportEntity::getReportTime, params.getStartDateTime());
        wrapper.le(ObjectUtil.isNotNull(params.getEndDateTime()), ReportEntity::getReportTime, params.getEndDateTime());
                // 批量日报信息查询
        wrapper.in(ObjectUtil.isNotEmpty(params.getReportIds()), ReportEntity::getId, params.getReportIds());
        wrapper.orderByAsc(ReportEntity::getReportTime);
        // 方法外移会看齐来比较简洁
        return list(wrapper);
    }

    @Override
    public JsonResult<?> saveReport (ReportPO report) {
        if (StrUtil.isBlank(report.getReportText())) {
            return JsonResult.fail("日报内容不能为空！");
        }
        Date reportTime = null;
        if (StrUtil.isBlank(report.getReportTime())) {
            reportTime = new Date();
        } else {
            reportTime = DateUtil.parse(report.getReportTime(), "yyyy-MM-dd");
        }
        ReportEntity reportEntity = new ReportEntity();
        BeanUtil.copyProperties(
                report,
                reportEntity,
                CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true).setIgnoreProperties("reportTime")
        );
        // 取出当前登录用户信息
        UserEntity currentLoginUser = UserChacheFromToken.getUser();
        // 设置日报人姓名 （取的是姓名，所以不能使用 creatorName）
        reportEntity.setReportName(currentLoginUser.getTruename());
        reportEntity.setReportTime(reportTime);
        saveOrUpdate(reportEntity);
        return JsonResult.ok();
    }

    @Override
    public void exportWeekReport(ReportPO param){
        // 获取模板文件
        ClassPathResource classPathResource = new ClassPathResource(workRportTemplate);
        try {
            // 填充个人信息和日期
            UserEntity user = UserChacheFromToken.getUser();
            FillData fillData = new FillData();
            fillData.setName(user.getTruename());
            fillData.setDepartment("技术部");

            // 获取模板
            InputStream inputStream = classPathResource.getInputStream();
            String today = DateUtil.format(new Date(),"yyyyMMdd");
            // 创建输出流
            ServletOutputStream outputStream = HttpServletUtil.getExportOutputStream(today+"周报-"+fillData.getName()+".xlsx");
            //填充Excel
            // 创建自定义workbook
            Workbook book = WorkbookUtil.createBook(inputStream, false);
            // 获取执行sheet
            Sheet sheet = book.getSheetAt(0);
            // 获取所有日报记录
            List<ReportEntity> entities = queryUserReportList(param) ;
            // 处理需要填充的数据
            List<WeekExportDTO> data = convertReportEntityToWeekExportDTO(entities);
            // 填充汇报日期 - 找出最大 reportTime 日期（因为查询结果按照 reportTime 升序，所以取最后一个）
            Date maxReportTime = entities.get(entities.size() - 1).getReportTime();
            fillData.setDate(DateUtil.format(maxReportTime, DatePattern.CHINESE_DATE_PATTERN));
            if (ObjectUtil.isNotEmpty(data)) {
                //填充相应字段数据 tableContents（sheet,开始行,填充数据,数据类型class）
                PoiUtil.tableContents(sheet, 6, data, WeekExportDTO.class);
                // 大于一才开始合并
                if (data.size() > 1) {
                    // 合并单元格 （开始行,结束行，开始列，结束列）
                    CellRangeAddress region01 = new CellRangeAddress(5, data.size() + 4, 0, 0);
                    sheet.addMergedRegion(region01);
                    CellRangeAddress region02 = new CellRangeAddress(5, data.size() + 4, 5, 5);
                    sheet.addMergedRegion(region02);
                }
            }
            // 替换数据
            EasyExcel.write(outputStream)
                    .withTemplate(changeOutToInput(new ByteArrayOutputStream(),book))
                    .sheet()
                    .doFill(fillData);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public List<WeekExportDTO> convertReportEntityToWeekExportDTO(List<ReportEntity> entity){
        // 判空
        if (ObjectUtil.isEmpty(entity)){
            return new ArrayList<>();
        }
        List<WeekExportDTO> list = new ArrayList<>();
        Map<String, WeekExportDTO> map = new LinkedHashMap<>();
        for (ReportEntity reportEntity : entity) {
            Week week = DateUtil.dayOfWeekEnum(reportEntity.getReportTime());
            String weekchinese = week.toChinese("周");
            // 处理工作项目填充类项目
            WeekExportDTO weekExportDTO;
            if (map.containsKey(weekchinese)){
                weekExportDTO = map.get(weekchinese);
            }else {
                weekExportDTO = new WeekExportDTO();
                map.put(weekchinese,weekExportDTO);
            }
            Integer orderNum = weekExportDTO.getOrderNum();
            orderNum++;
//            log.info("map ====> " + map);
            // 处理工作项目
            if (!StrUtil.isBlank(reportEntity.getModuleNames())) {
                weekExportDTO.getWorkModuleSet()
                        .add(reportEntity.getModuleNames().replaceAll("\\|",""));
            }
            //原计划完成目标
            weekExportDTO.getOriginalTargetSet()
                    //  例 1、完成商场订单接口实现
//                    .add(orderNum +reportEntity.getSplitChar()+reportEntity.getReportText());
                    .add(orderNum +reportEntity.getSplitChar()+reportEntity.getReportText() + "  " + reportEntity.getWorkProgress() + "%");
            //实际完成情况及数据说明
            weekExportDTO.getActualTargetSet()
                    //  例 1.完成商场订单接口实现 60%
                    .add(orderNum +reportEntity.getSplitChar()+reportEntity.getReportText()+"  "+ reportEntity.getWorkProgress() +"%");
//                    .add("按要求按时完成。");
            // 修改序号
            weekExportDTO.setOrderNum(orderNum);
        }
        // 处理导出数据
        for (Map.Entry<String, WeekExportDTO> entry : map.entrySet()) {
            String weekchinese = entry.getKey();
            WeekExportDTO value = entry.getValue();
//            value.setWorkModule(weekchinese +"  ("+ArrayUtil.join(value.getWorkModuleSet().toArray(new String[0]), "、")+" ) ");
            value.setWorkModule(
                    "（" + weekchinese + "）" + "\n" +
                    ArrayUtil.join(value.getWorkModuleSet().toArray(new String[0]), "\n")
            );
            value.setOriginalTarget(ArrayUtil.join(value.getOriginalTargetSet().toArray(new String[0]), "\n"));
//            value.setActualTarget(ArrayUtil.join(value.getActualTargetSet().toArray(new String[0]), "\n"));
            value.setActualTarget("按要求按时完成。");
            list.add(value);
        }
        return list;

    }

    /**
     *  数据流转换类 将 workbook 转换为 输入流
     * @param outputStream 输出流
     * @param workbook
     * @return
     */
    private InputStream changeOutToInput(ByteArrayOutputStream outputStream,Workbook workbook){
        try {
            workbook.write(outputStream);
            byte[] bytes = outputStream.toByteArray();
           return new ByteArrayInputStream(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new ByteArrayInputStream(new byte[0]);
    }

    /**
     *  制造输出数据的方法
     * @return
     */
    private List<WeekExportDTO> data() {
        List<WeekExportDTO> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            WeekExportDTO data = new WeekExportDTO();
            data.setWorkModule("字符串" + i);
            data.setActualTarget("nxjdjpapsoia");
            data.setOriginalTarget("测试测试");
            list.add(data);
        }
        return list;
    }

    @Override
    public JsonResult<?> statistics() {
        // 查出最近一周的日报
        Date startDateTime = null;
        Date endDateTime = null;
        // 处理开始时间 - 当前周的第一天: 周一
        Date currentDate = new Date();
        startDateTime = DateUtil.beginOfWeek(currentDate);
        // 处理结束时间 - 当前天
        endDateTime = DateUtil.endOfDay(currentDate);
        ReportPO queryParam = new ReportPO();
        queryParam.setStartDateTime(startDateTime);
        queryParam.setEndDateTime(endDateTime);
        log.info("queryParam ===>" + queryParam);
        // 执行查询
        List<ReportEntity> reportEntityList = queryUserReportList(queryParam);
        List<Map<String, Object>> weekReportRecordCountList = new ArrayList<>();
        for (ReportEntity reportEntity : reportEntityList) {
            boolean has = false;
            for (Map<String, Object> weekMap : weekReportRecordCountList) {
                if (weekMap.get("date").equals(DateUtil.dayOfWeekEnum(reportEntity.getReportTime()).toChinese("周"))) {
                    weekMap.put("count", (int) weekMap.get("count") + 1);
                    has = true;
                    break;
                }
            }
            if (!has) {
                Map<String, Object> weekMap = new HashMap<>();
                weekMap.put("date", DateUtil.dayOfWeekEnum(reportEntity.getReportTime()).toChinese("周"));
                weekMap.put("count", 1);
                weekReportRecordCountList.add(weekMap);
            }
        }
        log.info("weekReportRecordCountList ===>" + weekReportRecordCountList);
        // 查询今年的日报
        startDateTime = DateUtil.beginOfYear(currentDate);
        queryParam.setStartDateTime(startDateTime);
        log.info("queryParam2 ===>" + queryParam);
        List<ReportEntity> yearReportEntityList = queryUserReportList(queryParam);
        List<Map<String, Object>> yearReportRecordCountList = new ArrayList<>();
        for (ReportEntity reportEntity : yearReportEntityList) {
            boolean has = false;
            for (Map<String, Object> yearReportMap : yearReportRecordCountList) {
                if (yearReportMap.get("date").equals(DateUtil.monthEnum(reportEntity.getReportTime()).getValue())) {
                    yearReportMap.put("count", (int) yearReportMap.get("count") + 1);
                    has = true;
                    break;
                }
            }
            if (!has) {
                Map<String, Object> yearReportMap = new HashMap<>();
                yearReportMap.put("date", DateUtil.monthEnum(reportEntity.getReportTime()).getValue());
                yearReportMap.put("count", 1);
                yearReportRecordCountList.add(yearReportMap);
            }
        }
        log.info("yearReportRecordCountList ===>" + yearReportRecordCountList);
        Map<String, Object> res = new HashMap<>();
        res.put("weekReportRecordCountList", weekReportRecordCountList);
        res.put("yearReportRecordCountList", yearReportRecordCountList);
        res.put("yearReportRecordTotal", yearReportEntityList.size());
        return JsonResult.ok(res);
    }

    @Override
    public JsonResult<?> lastWorkDayReportSelf() {
        // 取出当前登录用户信息
        UserEntity currentLoginUser = UserChacheFromToken.getUser();
        // 查出最后一次提交的日报（排除今天的）
        LambdaQueryWrapper<ReportEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ReportEntity::getCreatorId, currentLoginUser.getId());
        wrapper.lt(ReportEntity::getReportTime, DateUtil.beginOfDay(new Date()));
        wrapper.orderByDesc(ReportEntity::getReportTime);
        wrapper.last(" limit 1 ");
        ReportEntity lastreportEntity = getOne( wrapper,false);
        log.info("lastreportEntity = " + lastreportEntity);
        List<ReportEntity> reportEntityList = new ArrayList<>();
        // 如果不为空，取出最后提交的时间
        if (!ObjectUtil.isEmpty(lastreportEntity)) {
            Date lastReportTime = lastreportEntity.getReportTime();
            ReportPO queryParam = new ReportPO();
            queryParam.setStartDateTime(DateUtil.beginOfDay(lastReportTime));
            queryParam.setEndDateTime(DateUtil.endOfDay(lastReportTime));
            // 查出最后一次时间提交的所有记录
            reportEntityList = queryUserReportList(queryParam);
        }
        return JsonResult.ok(reportEntityList);
    }

    @Override
    public void wrapEntity(ReportEntity entity) {

    }

    @Override
    public PageVO<ReportEntity> pageEntity(IPage<ReportEntity> page, Wrapper<ReportEntity> queryWrapper) {
        IPage<ReportEntity> pageResult = this.page(page, queryWrapper);
        return new PageVO<>(pageResult);
    }

    @Override
    public ReportEntity getByIdEntity(Integer id) {
        return null;
    }

    @Override
    public JsonResult saveOrUpdateEntity(ReportEntity entity) {
        return null;
    }

    @Override
    public JsonResult removeByIdEntity(Integer id) {
        return null;
    }

    @Override
    public JsonResult removeByIdsEntity(List<Integer> ids) {
        return null;
    }
}